//
//  SessionListController.swift
//  JKTools
//
//  Created by 姜奎 on 2/19/25.
//

import Cocoa

class SessionListController: NSViewController {

    static let AiLastSelectedSessionId = "AiLastSelectedSessionIdKey"

    @IBOutlet weak var outlineView: NSOutlineView!

    var selectedSessionId: String? {
        willSet {
            if newValue != nil {
                UserDefaults.standard.set(selectedSessionId, forKey: .lastSelectedSessionIdByAi)
            } else {
                UserDefaults.standard.removeObject(forKey: .lastSelectedSessionIdByAi)
            }
        }
    }

    var expandedItems: [String] = []

    private var observer: NSObjectProtocol?

    var onSelectSession: ((Session) -> Void)?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupOutlineView()
        loadMockData()
        setupNotificationObserver()
    }

    private func setupOutlineView() {


    }

    private func setupNotificationObserver() {

        observer = NotificationCenter.default.addObserver( forName: .delSession, object: nil, queue: .main) { [weak self] notification in

            guard let session = notification.userInfo?["session"] as? SessionEntity else { return }

            self?.deleteSession(with: session)

        }

    }

        // 数据加载和分组逻辑
    private func loadMockData() {
        AiStack.shared.fetchedResultController?.delegate = self
        try? AiStack.shared.fetchedResultController?.performFetch()
        self.outlineView.reloadData()
    }


    @IBAction func createNewMesssage(_ sender: NSButton) {
        AiStack.shared.insert(SessionEntity.self, datas: [Session.helloAi()]) { error in
            DispatchQueue.main.async {
                try? AiStack.shared.fetchedResultController?.performFetch()
            }
        }
    }
    
    deinit {
        if let observer = observer {
            NotificationCenter.default.removeObserver(observer)
        }
    }
}


extension SessionListController: NSFetchedResultsControllerDelegate {
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<any NSFetchRequestResult>) {

        outlineView.beginUpdates()
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<any NSFetchRequestResult>) {

        outlineView.endUpdates()
    }

    func controller(_ controller: NSFetchedResultsController<any NSFetchRequestResult>,
                    didChange sectionInfo: any NSFetchedResultsSectionInfo,
                    atSectionIndex sectionIndex: Int,
                    for type: NSFetchedResultsChangeType) {
        switch type {
            case .insert:
                self.outlineView.insertItems(at: IndexSet(integer: sectionIndex),
                                             inParent: nil,
                                             withAnimation: .slideDown)
            case .delete:
                self.outlineView.removeItems(at: IndexSet(integer: sectionIndex),
                                             inParent: nil,
                                             withAnimation: .slideUp)
            default:
                break
        }
    }

    func controller(_ controller: NSFetchedResultsController<any NSFetchRequestResult>,
                    didChange anObject: Any,
                    at indexPath: IndexPath?,
                    for type: NSFetchedResultsChangeType,
                    newIndexPath: IndexPath?) {

        switch type {
            case .insert:
//                guard let newIndexPath = newIndexPath else { return }
//                guard let session = anObject as? SessionEntity else { return }
//                guard let parent = AiStack.shared.fetchedResultController?.sections?.first(where: {$0.name == session.groupText}) else { return }
                self.outlineView.reloadData()
//                self.outlineView.expandItem(parent)
//                self.outlineView.insertItems(at: IndexSet(integer: newIndexPath.item),
//                                             inParent: parent,
//                                             withAnimation: .slideDown)


                self.selectedSession(with: anObject as? SessionEntity)

            case .delete:
                guard let indexPath = indexPath else { return }
                guard let session = anObject as? SessionEntity else { return }
                guard let parent = AiStack.shared.fetchedResultController?.sections?.first(where: {$0.name == session.groupText}) else { return }

                self.outlineView.removeItems(at: IndexSet(integer: indexPath.item),
                                             inParent: parent,
                                             withAnimation: .slideLeft)
                self.deleteSession(with: anObject as? SessionEntity)

            case .update:
                guard let session = anObject as? SessionEntity else { return }
                guard let parent = AiStack.shared.fetchedResultController?.sections?.first(where: {$0.name == session.groupText}) else { return }
                self.outlineView.reloadItem(parent, reloadChildren: false)

            default:
                break
        }
    }
}

extension SessionListController: NSOutlineViewDataSource {
        // MARK: - 数据源方法
    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
        // 根节点返回分组数，分组节点返回会话数
        guard let group = item as? NSFetchedResultsSectionInfo else { return AiStack.shared.fetchedResultController?.sections?.count ?? 0 }

        return group.numberOfObjects

    }

    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
            // 根节点返回分组对象，分组节点返回会话对象
        guard let group = item as? NSFetchedResultsSectionInfo else { return AiStack.shared.fetchedResultController!.sections![index] }

        return group.objects![index]
    }

    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
            // 只有分组对象可展开
        item is NSFetchedResultsSectionInfo
    }
}


extension SessionListController: NSOutlineViewDelegate {
        // MARK: - 视图代理
    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
        if let group = item as? NSFetchedResultsSectionInfo {
            return SessionListHeaderCell.createOrUpdate(outlineView, with: group.name)
        }


        if let session = item as? SessionEntity {
            return SessionListItemCell.createOrUpdate(outlineView, with: session)
        }
        return nil
    }

        // MARK: - 布局与交互
    func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
        item is NSFetchedResultsSectionInfo ? 28 : 50
    }


    func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
            // 自定义行视图实现交替背景色
        let rowView = NSTableRowView()
        rowView.isEmphasized = false
        return rowView
    }

    func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool {
            // 禁止选择分组标题行
        !(item is NSFetchedResultsSectionInfo)
    }

        // MARK: - 选择事件处理
    func outlineViewSelectionDidChange(_ notification: Notification) {
        guard outlineView.selectedRow != -1,
              let session = outlineView.item(atRow: outlineView.selectedRow) as? SessionEntity else {
            return
        }

        selectedSession(with: session)
    }

    func outlineViewItemDidExpand(_ notification: Notification) {
            // 展开分组时自动滚动到可见区域
        guard let group = notification.userInfo?["NSObject"] as? NSFetchedResultsSectionInfo else { return }
        let row = outlineView.row(forItem: group)
        outlineView.scrollRowToVisible(row)
    }

    func outlineView(_ outlineView: NSOutlineView, itemDidExpand item: Any) {
        guard let group = item as? NSFetchedResultsSectionInfo else { return }
        expandedItems.append(group.name)
        expandedItems.sort(by: <)
    }

    func outlineView(_ outlineView: NSOutlineView, itemDidCollapse item: Any) {
        guard let group = item as? NSFetchedResultsSectionInfo else { return }
        if let index = expandedItems.firstIndex(of: group.name) {
            expandedItems.remove(at: index)
        }
    }
}

extension SessionListController {
    private func selectedSession(with session: SessionEntity?) {
        guard let session = session else { return }
        if session.sessionId != selectedSessionId {
            selectedSessionId = "\(session.title)|\(session.id)"

                // 发送通知（替代之前的闭包回调）
            NotificationCenter.default.post(
                name: .didSelectSession,
                object: session.id,
                userInfo: nil
            )
        }
    }
    private func deleteSession(with session: SessionEntity?) {
        guard let session = session else { return }
        let objectId = session.objectID

        AiStack.shared.delete([objectId]) { _ in

        }

        if session.sessionId == selectedSessionId {
            selectedSessionId = nil

                // 发送通知（替代之前的闭包回调）
            NotificationCenter.default.post(
                name: .didSelectSession,
                object: nil,
                userInfo: nil
            )
        }
    }
}

extension Notification.Name {
    static let didSelectSession = Notification.Name("DidSelectAiSessionNotification")
}

extension String {
    static let lastSelectedSessionIdByAi = "AiLastSelectedSessionIdKey"
}
